/**
 *====================================================
 * 文件名称: FinanceTallyDeliveryActionApiImpl.java
 * 修订记录：
 * No    日期				作者(操作:具体内容)
 * 1.    2015年11月19日			chenxy(创建:创建文件)
 *====================================================
 * 类描述：(说明未实现或其它不应生成javadoc的内容)
 */
package com.yuexunit.finance.project.action.v1;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.yuexunit.core.BusinessException;
import com.yuexunit.core.ConfigPropertites;
import com.yuexunit.finance.bulkstock.entity.lexicon.MeasurementEnum;
import com.yuexunit.finance.common.util.BeanUtils;
import com.yuexunit.finance.common.util.CollectionUtils;
import com.yuexunit.finance.common.util.DateUtils;
import com.yuexunit.finance.common.util.HttpUtils;
import com.yuexunit.finance.common.util.LongUtils;
import com.yuexunit.finance.context.FinanceBaseAction;
import com.yuexunit.finance.context.FinanceLetterBlockingQueue;
import com.yuexunit.finance.context.FinanceSessionContext;
import com.yuexunit.finance.project.action.v1.dto.AbnormalCastor;
import com.yuexunit.finance.project.action.v1.dto.FinanceProcessCastor;
import com.yuexunit.finance.project.action.v1.dto.TallyingDeliveryCastor;
import com.yuexunit.finance.project.action.v1.model.input.ContainerTallyingSubmitAbnormalParams;
import com.yuexunit.finance.project.action.v1.model.input.ContainerTallyingSubmitParams;
import com.yuexunit.finance.project.action.v1.model.input.SignSyncParams;
import com.yuexunit.finance.project.action.v1.model.input.TallySyncParams;
import com.yuexunit.finance.project.action.v1.model.input.TallyingParams;
import com.yuexunit.finance.project.action.v1.model.input.TallyingUpdateParams;
import com.yuexunit.finance.project.action.v1.model.output.ContainerTallyingSubmitResponse;
import com.yuexunit.finance.project.action.v1.model.output.DeliveryDetail;
import com.yuexunit.finance.project.action.v1.model.output.DeliveryLineInfo;
import com.yuexunit.finance.project.action.v1.model.output.HandleSuitcaseResult;
import com.yuexunit.finance.project.action.v1.model.output.SupervisionConfirmationDetail;
import com.yuexunit.finance.project.action.v1.model.output.SyncTallyMessage;
import com.yuexunit.finance.project.action.v1.model.output.SyncTallyMessage.MessageDetail;
import com.yuexunit.finance.project.action.v1.model.output.TallyingDetail;
import com.yuexunit.finance.project.action.v1.model.output.TallyingLineInfo;
import com.yuexunit.finance.project.entity.AbnormalEntity;
import com.yuexunit.finance.project.entity.AbnormalInventoryEntity;
import com.yuexunit.finance.project.entity.ContainerBulkstockEntity;
import com.yuexunit.finance.project.entity.ContainerBulkstockHistoryEntity;
import com.yuexunit.finance.project.entity.ContainerInventoryEntity;
import com.yuexunit.finance.project.entity.ContainerInventoryHistoryEntity;
import com.yuexunit.finance.project.entity.ContainerInventoryRelieveEntity;
import com.yuexunit.finance.project.entity.ContainerInventorySignEntity;
import com.yuexunit.finance.project.entity.ContainerInventoryTallyEntity;
import com.yuexunit.finance.project.entity.DeliveryEntity;
import com.yuexunit.finance.project.entity.DeliveryNoticeEntity;
import com.yuexunit.finance.project.entity.FinanceApplicationEntity;
import com.yuexunit.finance.project.entity.FinanceBulkstockEntity;
import com.yuexunit.finance.project.entity.FinanceContainerEntity;
import com.yuexunit.finance.project.entity.FinanceContainerLogEntity;
import com.yuexunit.finance.project.entity.FinanceCreditEntity;
import com.yuexunit.finance.project.entity.FinanceProcessDetailEntity;
import com.yuexunit.finance.project.entity.FinanceProcessEntity;
import com.yuexunit.finance.project.entity.PickupApplicationEntity;
import com.yuexunit.finance.project.entity.PickupBulkstockEntity;
import com.yuexunit.finance.project.entity.PickupExchangeContainerBulkstockEntity;
import com.yuexunit.finance.project.entity.PickupExchangeContainerEntity;
import com.yuexunit.finance.project.entity.PickupInventoryEntity;
import com.yuexunit.finance.project.entity.RecieveNoticeEntity;
import com.yuexunit.finance.project.entity.RecieveNoticeInventoryEntity;
import com.yuexunit.finance.project.entity.SupervisionConfirmationEntity;
import com.yuexunit.finance.project.entity.TallyingEntity;
import com.yuexunit.finance.project.entity.lexicon.AbnormalStateEnum;
import com.yuexunit.finance.project.entity.lexicon.AbnormalTypeEnum;
import com.yuexunit.finance.project.entity.lexicon.ApplicationStateEnum;
import com.yuexunit.finance.project.entity.lexicon.BulkstockSourceEnum;
import com.yuexunit.finance.project.entity.lexicon.DeliveryStateEnum;
import com.yuexunit.finance.project.entity.lexicon.ExchangeStatusEnum;
import com.yuexunit.finance.project.entity.lexicon.FinanceStateEnum;
import com.yuexunit.finance.project.entity.lexicon.NoticeStateEnum;
import com.yuexunit.finance.project.entity.lexicon.ProductTypeEnum;
import com.yuexunit.finance.project.entity.lexicon.SupervisionStateEnum;
import com.yuexunit.finance.project.entity.lexicon.TallyingStateEnum;
import com.yuexunit.finance.project.service.AbnormalInventoryService;
import com.yuexunit.finance.project.service.AbnormalService;
import com.yuexunit.finance.project.service.FinanceContainerLogService;
import com.yuexunit.finance.project.service.PickupExchangeContainerBulkstockService;
import com.yuexunit.finance.project.service.PickupExchangeContainerService;
import com.yuexunit.finance.system.action.v1.dto.SendLetterMessage;
import com.yuexunit.fs.domain.FileEntry;
import com.yuexunit.fs.parse.service.FileParseService;
import com.yuexunit.fs.service.TransferService;
import com.yuexunit.inject.ComponentFactory;
import com.yuexunit.inject.annotation.Implements;
import com.yuexunit.jsonutil.JSON;
import com.yuexunit.page.PageCriteria;
import com.yuexunit.page.PageList;
import com.yuexunit.persist.annotation.Transactional;
import com.yuexunit.util.DateUtil;

/**
 * @ClassName: FinanceTallyDeliveryActionApiImpl
 * @Description: 理货配送
 * @author chenxy
 * @date 2015年11月19日 下午8:50:59
 */
@Implements(FinanceTallyDeliveryActionApi.class)
public class FinanceTallyDeliveryActionApiImpl extends FinanceBaseAction implements FinanceTallyDeliveryActionApi {

	private static Logger LOG = LoggerFactory.getLogger(FinanceTallyDeliveryActionApiImpl.class);

	private AbnormalService abnormalService = ComponentFactory.loadClass(AbnormalService.class);

	private AbnormalInventoryService abnormalInventoryService = ComponentFactory.loadClass(AbnormalInventoryService.class);

	private PickupExchangeContainerService pickupExchangeContainerService = ComponentFactory.loadClass(PickupExchangeContainerService.class);

	private PickupExchangeContainerBulkstockService pickupExchangeContainerBulkstockService = ComponentFactory.loadClass(PickupExchangeContainerBulkstockService.class);

	private FinanceContainerLogService financeContainerLogService = ComponentFactory.loadClass(FinanceContainerLogService.class);

	private TransferService transferService = ComponentFactory.loadClass(TransferService.class);

	private FinanceApplicationActionApi financeApplicationActionApi = ComponentFactory.loadClass(FinanceApplicationActionApi.class);

	private FinanceApplicationActionApiImpl financeApplicationActionApiImpl = ComponentFactory.loadClass(FinanceApplicationActionApiImpl.class);
	
	private String tmp = "客户(%s)融资(%s)目前处于(%s)环节，请及时处理！";
	
	private List<String> INVENTORY_TITLES = Arrays.asList(new String[] { "货物名称", "规格型号", "箱号", "运单号", "重量", "数量", "体积" });

	public void processFinanceBulkstock(ContainerInventoryEntity last) {
		FinanceApplicationEntity finance = financeApplicationService.inquireFinanceApplicationEntity(last.getFinanceId());
		// 尾箱差值计算
		FinanceContainerEntity container = financeContainerService.inquireFinanceContainer(finance.getFinanceId());
		Integer quantity = container.getCaseQuantity();
		if (quantity == null) {
			throw new BusinessException("箱量未填写..");
		}
		if (quantity != null && last != null) {
			List<ContainerInventoryEntity> inventories = containerInventoryService.inquireSupervisionFinanceAmountList(finance.getFinanceId());
			if (inventories.size() == quantity.intValue()) {
				BigDecimal amount = BigDecimal.ZERO;
				for (ContainerInventoryEntity cie : inventories) {
					//					amount = amount.add(cie.getAdjustment());
					List<ContainerBulkstockEntity> cbes = containerBulkstockService.inquireContainerBulkstockList(cie.getInventoryId());
					for (ContainerBulkstockEntity cbe : cbes) {
						amount = amount.add(cbe.getValuationFinanceAmount());
					}
				}
				last.setAdjustment(finance.getFinanceAmount().subtract(amount));
				containerInventoryService.renovateContainerInventory(last);
			}
		}
		// 未填写箱量时,融资货物的总额不允许超过融资金额(货物的融资金额根据融资单价*重量<现系统中货物的计量标准只使用重量,体积的暂不考虑>)
		//		if (quantity == null || quantity.intValue() <= 0) {
		//			List<ContainerInventoryEntity> inventories = containerInventoryService.inquireSupervisionFinanceAmountList(finance.getFinanceId());
		//			BigDecimal amount = BigDecimal.ZERO;
		//			for (ContainerInventoryEntity cie : inventories) {
		//				amount = amount.add(cie.getAdjustment());
		//				List<ContainerBulkstockEntity> cbes = containerBulkstockService.inquireContainerBulkstockList(cie.getInventoryId());
		//				for (ContainerBulkstockEntity cbe : cbes) {
		//					amount = amount.add(cbe.getValuationFinanceAmount());
		//				}
		//			}
		//			if (amount.compareTo(finance.getFinanceAmount()) == 1) {
		//				latest.setAdjustment(latest.getAdjustment().add(finance.getFinanceAmount().subtract(amount)));
		//				containerInventoryService.renovateContainerInventory(latest);
		//			}
		//		}
	}

	private void processPickupBulkstockAcceptance(ContainerInventoryEntity inventory) {
		List<RecieveNoticeEntity> recieveNotices = recieveNoticeService.inquireExchangeRecieveNotice(inventory.getExchangePickupId());
		for (RecieveNoticeEntity recieveNotice : recieveNotices) {
			if (NoticeStateEnum.FINISHED != recieveNotice.getNoticeState()) {
				throw new BusinessException("该收货通知物流公司还未完成,无法进入监管");
			}
		}
		PickupApplicationEntity pickup = pickupApplicationService.inquirePickupApplication(inventory.getExchangePickupId());
		inventory.setLoanNoticeId(pickup.getLoanNoticeId());
		List<ContainerInventoryEntity> inventories = containerInventoryService.inquireExchangeContainerInventoryList(inventory.getExchangePickupId());
		for (ContainerInventoryEntity cie : inventories) {
			if (inventory.getInventoryId().equals(cie.getInventoryId())) {
				continue;
			}
			if (SupervisionStateEnum.ALREADY_REPORT == cie.getSupervisionState()) {
				return;
			}
		}
		// 新进换货箱尾箱差值调整
		BigDecimal exchangeFinanceAmount = pickup.getFinanceValuation();
		for (ContainerInventoryEntity cie : inventories) {
			List<ContainerBulkstockEntity> bulkstocks = containerBulkstockService.inquireContainerBulkstockList(cie.getInventoryId());
			for (ContainerBulkstockEntity cbe : bulkstocks) {
				exchangeFinanceAmount = exchangeFinanceAmount.subtract(cbe.getValuationFinanceAmount());
			}
			exchangeFinanceAmount = exchangeFinanceAmount.subtract(cie.getAdjustment());
		}
		inventory.setAdjustment(exchangeFinanceAmount);
		// 添加箱量
		FinanceContainerEntity financeContainer = financeContainerService.inquireFinanceContainer(inventory.getFinanceId());
		financeContainer.setCaseQuantity(financeContainer.getCaseQuantity() + inventories.size());
		financeContainerService.renovateFinanceContainer(financeContainer);
	}

	private void processCreditBulkstockAcceptance(ContainerInventoryEntity container) {
		List<RecieveNoticeEntity> recieveNotices = recieveNoticeService.inquireReplenishRecieveNotice(container.getReplenishCreditId());
		for (RecieveNoticeEntity recieveNotice : recieveNotices) {
			if (NoticeStateEnum.FINISHED != recieveNotice.getNoticeState()) {
				throw new BusinessException("该收货通知物流公司还未完成,无法进入监管");
			}
		}
		List<ContainerInventoryEntity> inventories = containerInventoryService.inquireReplenishContainerInventoryList(container.getReplenishCreditId());
		for (ContainerInventoryEntity cie : inventories) {
			if (container.getInventoryId().equals(cie.getInventoryId())) {
				continue;
			}
			if (SupervisionStateEnum.ALREADY_REPORT != cie.getSupervisionState()) { // 全部确认收货时,开始平摊融资金额
				return;
			}
		}
		// 新进补货箱尾箱差值调整
		FinanceCreditEntity credit = financeCreditService.inquireFinanceCredit(container.getReplenishCreditId());
		BigDecimal replenishFinanceAmount = credit.getReplenishFinanceAmount();
		for (ContainerInventoryEntity cie : inventories) {
			List<ContainerBulkstockEntity> bulkstocks = containerBulkstockService.inquireContainerBulkstockList(cie.getInventoryId());
			for (ContainerBulkstockEntity cbe : bulkstocks) {
				replenishFinanceAmount = replenishFinanceAmount.subtract(cbe.getValuationFinanceAmount());
			}
			replenishFinanceAmount = replenishFinanceAmount.subtract(cie.getAdjustment());
		}
		container.setAdjustment(replenishFinanceAmount);

		// 添加箱量
		FinanceContainerEntity financeContainer = financeContainerService.inquireFinanceContainer(container.getFinanceId());
		financeContainer.setCaseQuantity(financeContainer.getCaseQuantity() + inventories.size());
		financeContainerService.renovateFinanceContainer(financeContainer);
	}

	// ========================================================================================================================//
	@Transactional
	@Override
	public String createTallying(TallyingParams tallyingParams) {
		Long tallyingId = null;
		TallyingEntity tallying = TallyingDeliveryCastor.fromRecieveNoticeEntity(tallyingParams);
		if (tallyingParams.getCaseQueue() == null || tallyingParams.getCaseQueue().length == 0) {
			tallying.setUserDefined(Boolean.TRUE);
		} else {
			tallying.setUserDefined(Boolean.FALSE);
		}
		if (tallying.getUserDefined()) {
			tallyingId = tallyingService.createTallying(tallying);
			return tallyingId.toString();
		}
		// 非自理货箱处理
		Map<String, List<TallyingEntity>> queueTallys = TallyingDeliveryCastor.fromTallying(tallying, tallyingParams);
		for (List<TallyingEntity> tallys : queueTallys.values()) {
			for (TallyingEntity tally : tallys) {
				tallyingId = tallyingService.createTallying(tally);
				ContainerInventoryHistoryEntity container = tally.getContainerInventoryHistory();
				container.setTallyingId(tallyingId);
				containerInventoryHistoryService.createContainerInventory(container);
			}
		}
		// 更新通知已计划数量
		List<RecieveNoticeInventoryEntity> noticeInventoryList = recieveNoticeInventoryService.inquireRecieveNoticeInventoryList(tallying.getRecieveNoticeId());
		Map<Long, RecieveNoticeInventoryEntity> noticeInventories = new HashMap<>();
		for (RecieveNoticeInventoryEntity rnie : noticeInventoryList) {
			noticeInventories.put(rnie.getBulkstockId(), rnie);
		}
		List<ContainerBulkstockHistoryEntity> bulkstockEntities = TallyingDeliveryCastor.fromTallying(tallying, queueTallys, tallyingParams);
		for (ContainerBulkstockHistoryEntity bulkstock : bulkstockEntities) {
			bulkstock.setTallyingId(tallyingId);
			containerBulkstockHistoryService.createContainerBulkstock(bulkstock);
			if (bulkstock.getPlannedQuantity() != null && noticeInventories.containsKey(bulkstock.getBulkstockId())) {
				RecieveNoticeInventoryEntity noticeInventory = noticeInventories.get(bulkstock.getBulkstockId());
				if (noticeInventory.getPlannedQuantity() == null) {
					noticeInventory.setPlannedQuantity(BigDecimal.ZERO);
				}
				noticeInventory.setPlannedQuantity(noticeInventory.getPlannedQuantity().add(bulkstock.getPlannedQuantity()));
				if (noticeInventory.getPlannedQuantity().compareTo(noticeInventory.getQuantity()) > 0) {
					throw new BusinessException("计划数量超出收货通知任务数量");
				}
			}
		}
		for (RecieveNoticeInventoryEntity rnie : noticeInventoryList) {
			recieveNoticeInventoryService.renovateRecieveNoticeInventory(rnie);
		}
		// try {
		// FileWriter output = new FileWriter("C://test1.txt");
		// BufferedWriter bf = new BufferedWriter(output);
		// bf.write("clerkId=" + tallying.getClerkId() + "\r\n");
		// bf.flush();
		// bf.close();
		// } catch (Exception e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// }
		if (tallying.getClerkId() != null) {
			FinanceLetterBlockingQueue.putCompanyTallyTaskLetter(tallying.getClerkId(), tallying.getLogisticsCompanyId(), "理货任务信息", "tally.clerk.notice", tallyingService.inquireTallying(tallyingId).getTallyingNumber());
		}
		return tallyingId.toString();
	}

	@Transactional
	@Override
	public void updateTallying(TallyingUpdateParams params) {
		Long tallyingId = params.getTallyingId();
		TallyingEntity persist = tallyingService.inquireTallyingDetail(tallyingId);
		if (TallyingStateEnum.WAIT_TALLY != persist.getTallyingState() && TallyingStateEnum.REFUSE != persist.getTallyingState()) {
			throw new BusinessException("该理货任务已确认,不允许修改");
		}
		RecieveNoticeEntity recieveNotice = recieveNoticeService.inquireRecieveNoticeDetail(params.getRecieveNoticeId());
		TallyingEntity tallying = TallyingDeliveryCastor.fromRecieveNoticeEntity(params);
		tallying.setTallyingId(tallyingId);
		if (params.getCaseQueue() == null || params.getCaseQueue().length == 0) {
			if (BulkstockSourceEnum.REPEAT == recieveNotice.getBulkstockSource()) {
				throw new BusinessException("再次理货任务不允许删除计划理货箱信息");
			}
			tallying.setUserDefined(Boolean.TRUE);
		} else {
			tallying.setUserDefined(Boolean.FALSE);
		}
		tallyingService.updateTallying(tallying);
		if (BulkstockSourceEnum.REPEAT == recieveNotice.getBulkstockSource()) { // 再次理货任务不允许修改计划箱/货信息
			return;
		}
		// 更新通知已计划数量
		List<RecieveNoticeInventoryEntity> noticeInventoryList = recieveNoticeInventoryService.inquireRecieveNoticeInventoryList(tallying.getRecieveNoticeId());
		Map<Long, RecieveNoticeInventoryEntity> noticeInventories = new HashMap<>();
		for (RecieveNoticeInventoryEntity rnie : noticeInventoryList) {
			noticeInventories.put(rnie.getBulkstockId(), rnie);
		}

		// 获取原有计划箱数据
		ContainerInventoryHistoryEntity inventory = null;
		List<ContainerInventoryHistoryEntity> inventoryList = containerInventoryHistoryService.inquireTallyingContainerInventoryList(tallyingId);
		if (!inventoryList.isEmpty()) {
			inventory = inventoryList.get(0);
		}

		List<ContainerBulkstockHistoryEntity> bulkstockList = containerBulkstockHistoryService.inquireTallyingContainerBulkstockList(tallyingId);
		for (ContainerBulkstockHistoryEntity bulkstock : bulkstockList) {
			if (bulkstock.getPlannedQuantity() != null && noticeInventories.containsKey(bulkstock.getBulkstockId())) {
				RecieveNoticeInventoryEntity noticeInventory = noticeInventories.get(bulkstock.getBulkstockId());
				noticeInventory.setPlannedQuantity(noticeInventory.getPlannedQuantity().subtract(bulkstock.getPlannedQuantity()));
			}
		}
		if (tallying.getUserDefined() && inventory != null) { // 自理货箱处理
			containerInventoryHistoryService.deleteContainerInventory(inventory.getInventoryHistoryId());
			for (ContainerBulkstockHistoryEntity bulkstock : bulkstockList) {
				containerBulkstockHistoryService.deleteContainerBulkstock(bulkstock.getBulkstockHistoryId());
			}
			return;
		}
		// 非自理货箱处理 保存提交数据 修改理货任务-不允许多箱量(只允许修改一个箱)
		Map<String, List<TallyingEntity>> queueTally = TallyingDeliveryCastor.fromTallying(tallying, params);
		for (List<TallyingEntity> tallys : queueTally.values()) {
			TallyingEntity tally = tallys.get(0);
			tally.setTallyingId(tallyingId);
			ContainerInventoryHistoryEntity container = tally.getContainerInventoryHistory();
			container.setTallyingId(tallyingId);
			if (inventory != null) {
				container.setInventoryHistoryId(inventory.getInventoryHistoryId());
				containerInventoryHistoryService.updateContainerInventory(container);
			} else {
				containerInventoryHistoryService.createContainerInventory(container);
			}
			break;
		}
		List<ContainerBulkstockHistoryEntity> bulkstockEntities = TallyingDeliveryCastor.fromTallying(tallying, queueTally, params);
		for (ContainerBulkstockHistoryEntity bulkstock : bulkstockEntities) {
			ContainerBulkstockHistoryEntity exists = null;
			for (ContainerBulkstockHistoryEntity p : bulkstockList) {
				if (p.getBulkstockHistoryId().equals(bulkstock.getBulkstockHistoryId())) {
					exists = p;
				}
			}
			if (exists != null) {
				containerBulkstockHistoryService.updateContainerBulkstock(bulkstock);
			} else {
				containerBulkstockHistoryService.createContainerBulkstock(bulkstock);
			}
			bulkstockList.remove(exists);
			if (bulkstock.getPlannedQuantity() != null && noticeInventories.containsKey(bulkstock.getBulkstockId())) {
				RecieveNoticeInventoryEntity noticeInventory = noticeInventories.get(bulkstock.getBulkstockId());
				noticeInventory.setPlannedQuantity(noticeInventory.getPlannedQuantity().add(bulkstock.getPlannedQuantity()));
				if (noticeInventory.getPlannedQuantity().compareTo(noticeInventory.getQuantity()) > 0) {
					throw new BusinessException("计划数量超出收货通知任务数量");
				}
			}
		}
		if (!bulkstockList.isEmpty()) {
			throw new BusinessException("修改理货任务不允许删除箱中货物信息");
		}
		for (RecieveNoticeInventoryEntity rnie : noticeInventoryList) {
			recieveNoticeInventoryService.renovateRecieveNoticeInventory(rnie);
		}
	}

	@Transactional
	@Override
	public void deleteTallying(Long tallyingId) {
		TallyingEntity persist = tallyingService.inquireTallyingDetail(tallyingId);
		if (TallyingStateEnum.WAIT_TALLY != persist.getTallyingState() || TallyingStateEnum.REFUSE != persist.getTallyingState()) {
			throw new BusinessException("该理货任务已确认,不允许删除");
		}
		RecieveNoticeEntity recieveNotice = recieveNoticeService.inquireRecieveNoticeDetail(persist.getRecieveNoticeId());
		if (BulkstockSourceEnum.REPEAT == recieveNotice.getBulkstockSource()) {
			throw new BusinessException("再次理货任务,不允许删除");
		}
		tallyingService.deleteTallying(tallyingId);
		List<ContainerInventoryHistoryEntity> inventoryEntityList = containerInventoryHistoryService.inquireTallyingContainerInventoryList(tallyingId);
		for (ContainerInventoryHistoryEntity inventoryEntity : inventoryEntityList) {
			containerInventoryHistoryService.deleteContainerInventory(inventoryEntity.getInventoryHistoryId());
		}
		List<ContainerBulkstockHistoryEntity> bulkstockList = containerBulkstockHistoryService.inquireTallyingContainerBulkstockList(tallyingId);
		for (ContainerBulkstockHistoryEntity bulkstock : bulkstockList) {
			containerBulkstockHistoryService.deleteContainerBulkstock(bulkstock.getBulkstockHistoryId());
		}
	}

	@Transactional
	@Override
	public void confirmTallying(Long tallyingId) {
		TallyingEntity tallyingEntity = tallyingService.inquireTallyingDetail(tallyingId);
		if (TallyingStateEnum.WAIT_TALLY != tallyingEntity.getTallyingState()) {
			throw new BusinessException("该任务已经被确认");
		}
		tallyingEntity.setTallyingState(TallyingStateEnum.IN_TALLY);
		tallyingService.renovateTallying(tallyingEntity);
	}

	@Transactional
	@Override
	public ContainerTallyingSubmitResponse submitContainerTallying(ContainerTallyingSubmitParams params) {
		params.setCaseNumber(params.getCaseNumber().trim().toUpperCase());
		params.setWaybillNumber(params.getWaybillNumber().trim().toUpperCase());
		if (params.getLogisticsCompanyInfoId() == 1) {
			//若是安通的货箱，则验证是否正确
			HandleSuitcaseResult result = financeApplicationActionApi.containerTaken(params.getWaybillNumber(), params.getCaseNumber());
			if (result != null && result.getResult() == false) {
				throw new BusinessException(result.getMessage());
			}
		}
		if (params.getRecieveNoticeDetailId() == null || params.getRecieveNoticeDetailId().length == 0) {
			throw new BusinessException("提交的箱货信息不允许为空");
		}
		TallyingEntity tallying = tallyingService.inquireTallyingDetail(params.getTallyingId());
		if (TallyingStateEnum.ALREADY_TALLY == tallying.getTallyingState()) {
			throw new BusinessException("理货任务已完成");
		}
		RecieveNoticeEntity recieveNotice = recieveNoticeService.inquireRecieveNoticeDetail(tallying.getRecieveNoticeId());
		if (BulkstockSourceEnum.LOGISTICS == recieveNotice.getBulkstockSource()) { // 物流自理
			List<ContainerInventoryHistoryEntity> list = containerInventoryHistoryService.inquireLogisticsContainerInventoryList(params.getWaybillNumber(), params.getCaseNumber());
			for (ContainerInventoryHistoryEntity p : list) {
				if (!p.getInventoryHistoryId().equals(params.getInventoryHistoryId())) {
					throw new BusinessException("提交的箱货信息已存在理货信息");
				}
			}
		} else {
			List<ContainerInventoryHistoryEntity> persists = containerInventoryHistoryService.inquireRecieveNoticeContainerInventory(params.getWaybillNumber(), params.getCaseNumber());
			//			if (persists != null && !persists.isEmpty()) {
			//				throw new BusinessException("提交的箱货信息已存在理货信息");
			//			}
			for (ContainerInventoryHistoryEntity persist : persists) {
				if (persist.getInventoryHistoryId().equals(params.getInventoryHistoryId()) && persist.getTallyingState()) {
					throw new BusinessException("提交的箱货信息已完成理货");
				}
				//				if (BulkstockSourceEnum.REPEAT != recieveNotice.getBulkstockSource()) {
				//					throw new BusinessException("提交的箱货信息已存在");
				//				}
			}
		}

		//		ContainerInventoryEntity cie = containerInventoryService.inquireContainerInventory(params.getWaybillNumber(), params.getCaseNumber());
		//		if (cie != null) {
		//			throw new BusinessException("提交的箱货信息已存在理货信息");
		//		}
		// 确定货物来源是否统一(融资/补货/提货 三种来源不允许混合) 验证货源一致
		for (Long recieveNoticeBulkstockId : params.getRecieveNoticeDetailId()) {
			RecieveNoticeInventoryEntity recieveNoticeBulkstock = recieveNoticeInventoryService.inquireRecieveNoticeDetail(recieveNoticeBulkstockId);
			if (!recieveNoticeBulkstock.getRecieveNoticeId().equals(recieveNotice.getRecieveNoticeId())) {
				throw new BusinessException("货物信息不在收货通知中");
			}
		}
		tallying.setTallyingState(TallyingStateEnum.IN_TALLY);
		tallyingService.renovateTallying(tallying);

		ContainerInventoryHistoryEntity inventory = new ContainerInventoryHistoryEntity();
		if (!LongUtils.isPrimaryKey(params.getInventoryHistoryId())) {
			inventory.setRecieveNoticeId(tallying.getRecieveNoticeId());
			containerInventoryHistoryService.createContainerInventory(inventory);
		}
		// 货箱信息&理货信息
		TallyingDeliveryCastor.completeFromTallyingSubmit(inventory, tallying, params);
		containerInventoryHistoryService.updateContainerInventory(inventory);
		List<ContainerBulkstockHistoryEntity> bulkstockEntities = TallyingDeliveryCastor.fromTallyingSubmit(params, inventory);
		for (ContainerBulkstockHistoryEntity bulkstock : bulkstockEntities) {
			if (!LongUtils.isPrimaryKey(bulkstock.getBulkstockHistoryId())) {
				containerBulkstockHistoryService.createContainerBulkstock(bulkstock);
			} else {
				containerBulkstockHistoryService.updateContainerBulkstock(bulkstock);
			}
			RecieveNoticeInventoryEntity noticeInventory = recieveNoticeInventoryService.inquireRecieveNoticeDetail(bulkstock.getNoticeInventoryId());
			if (noticeInventory == null) {
				throw new BusinessException("货物信息不在收货通知中");
			}
			if (params.getType() == null || !params.getType().equals("update")) {
				noticeInventory.setTallying(noticeInventory.getTallying().add(bulkstock.getQuantity()));
				recieveNoticeInventoryService.renovateRecieveNoticeInventory(noticeInventory);
			}
		}
		ContainerTallyingSubmitResponse response = new ContainerTallyingSubmitResponse();
		response.setInventoryHistoryId(inventory.getInventoryHistoryId());
		response.setTallyingState(BooleanUtils.toIntegerObject(inventory.getTallyingState()));
		response.setTallyDateTime(inventory.getTallyDateTime());
		return response;
	}

	@Transactional
	@Override
	public void supplementAbnormalContainerTallying(ContainerTallyingSubmitAbnormalParams params) {
		params.setAbnormal(0);
		TallyingEntity tallying = tallyingService.inquireTallyingDetail(params.getTallyingId());
		if (TallyingStateEnum.ALREADY_TALLY == tallying.getTallyingState()) {
			throw new BusinessException("理货任务已完成");
		}
		if (params.getInventoryHistoryId() == null) {
			throw new BusinessException("理货货箱标识 inventoryHistoryId 不允许为空");
		}
		ContainerInventoryHistoryEntity inventory = containerInventoryHistoryService.inquireContainerInventory(params.getInventoryHistoryId());
		if (inventory == null) {
			throw new BusinessException("直接异常上报请调用 submitContainerTallying 接口");
		}
		BeanUtils.copyProperties(params, inventory);
		inventory.setAbnormal(BooleanUtils.toBoolean(params.getAbnormal()));
		if (inventory.validateAbnormal()) {
			inventory.setAbnormalType(AbnormalTypeEnum.TALLY);
			inventory.setAbnormalState(AbnormalStateEnum.valueOf(params.getTallyExAbnormalState()));
		}
		inventory.setTallyExAbnormalState(AbnormalStateEnum.valueOf(params.getTallyExAbnormalState()));
		containerInventoryHistoryService.renovateContainerInventory(inventory);
	}

	@Override
	public void supplementTallyContainerInventory(Long inventoryHistoryId, String tallyPreFile, String tallySuffixFile) {
		ContainerInventoryHistoryEntity inventory = containerInventoryHistoryService.inquireContainerInventory(inventoryHistoryId);
		if (StringUtils.isNotBlank(tallyPreFile)) {
			if (StringUtils.isNotBlank(inventory.getTallyPreFile())) {
				inventory.setTallyPreFile(inventory.getTallyPreFile() + "," + tallyPreFile);
			} else {
				inventory.setTallyPreFile(tallyPreFile);
			}
		}
		if (StringUtils.isNotBlank(tallySuffixFile)) {
			if (StringUtils.isNotBlank(inventory.getTallySuffixFile())) {
				inventory.setTallySuffixFile(inventory.getTallySuffixFile() + "," + tallySuffixFile);
			} else {
				inventory.setTallySuffixFile(tallySuffixFile);
			}
		}
		containerInventoryHistoryService.renovateContainerInventory(inventory);
	}

	@Override
	public void supplementTallyContainerBulkstock(Long bulkstockHistoryId, String filesUuid) {
		ContainerBulkstockHistoryEntity bulkstock = containerBulkstockHistoryService.inquireContainerBulkstock(bulkstockHistoryId);
		if (StringUtils.isNotBlank(filesUuid)) {
			if (StringUtils.isNotBlank(bulkstock.getFilesUuid())) {
				bulkstock.setFilesUuid(bulkstock.getFilesUuid() + "," + filesUuid);
			} else {
				bulkstock.setFilesUuid(filesUuid);
			}
			containerBulkstockHistoryService.renovateContainerBulkstock(bulkstock);
		}
	}

	@Override
	@Transactional
	public void supplementTallyExchangeContainerInventory(Long containerId, String clerkMobile, Date tallyStartDateTime, Date tallyDateTime, String tallyAddress, String tallyPreFile, String tallySuffixFile, String tallyRemark,
			String tallyExAddress, String tallyExRemark, String tallyExAbnormalFile, Integer tallyExAbnormalState, String caseSize, String waybillNumber, String facingSlip, BigDecimal quantity, BigDecimal weight, BigDecimal volume,
			String trayNumber, String clerk) {
		PickupExchangeContainerEntity container = pickupExchangeContainerService.inquirePickupExchangeContainerDetail(containerId);
		container.setClerkMobile(clerkMobile);
		container.setTallyStartDateTime(tallyStartDateTime);
		container.setTallyDateTime(tallyDateTime);
		container.setTallyAddress(tallyAddress);
		container.setTallyPreFile(tallyPreFile);
		container.setTallySuffixFile(tallySuffixFile);
		container.setTallyRemark(tallyRemark);
		container.setTallyExAddress(tallyExAddress);
		container.setTallyExRemark(tallyExRemark);
		container.setTallyExAbnormalFile(tallyExAbnormalFile);
		container.setTallyExAbnormalState(AbnormalStateEnum.valueOf(tallyExAbnormalState));
		container.setCaseSize(caseSize);
		container.setWaybillNumber(waybillNumber);
		container.setFacingSlip(facingSlip);
		container.setClerk(clerk);
		container.setOperateDate(DateUtil.now());
		container.setOperator(FinanceSessionContext.getAccountFullName());

		PickupExchangeContainerBulkstockEntity bulkstock = pickupExchangeContainerBulkstockService.inquirePickupExchangeContainerBulkstockList(containerId).get(0);
		bulkstock.setTallyQuantity(quantity);
		bulkstock.setTallyWeight(weight);
		bulkstock.setTallyVolume(volume);
		if (bulkstock.getQuantity() == null) {
			bulkstock.setQuantity(bulkstock.getTallyQuantity());
		}
		if (bulkstock.getWeight() == null) {
			bulkstock.setWeight(bulkstock.getTallyWeight());
		}
		if (bulkstock.getVolume() == null) {
			bulkstock.setVolume(bulkstock.getTallyVolume());
		}
		bulkstock.setTrayNumber(trayNumber);

		pickupExchangeContainerBulkstockService.renovatePickupExchangeContainerBulkstock(bulkstock);
		pickupExchangeContainerService.renovatePickupExchangeContainer(container);
		pickupExchangeContainerService.renovatePickupExchangeContainer(container);
		boolean sync = true;
		PickupApplicationEntity pickup = pickupApplicationService.inquirePickupApplication(container.getPickupId());
		List<PickupExchangeContainerEntity> peces = pickupExchangeContainerService.inquirePickupExchangeContainerList(container.getPickupId());
		for (PickupExchangeContainerEntity p : peces) {
			if (p.getTallyDateTime() == null) {
				sync = false;
			}
		}
		if (sync) { // 理货同步完成
			pickup.setExchangeStatus(ExchangeStatusEnum.CONCLUDE);
			pickupApplicationService.renovatePickupApplication(pickup);
		}
	}

	@Transactional
	@Override
	public void finishedTallying(Long tallyingId, String finishedFileUuid) {
		List<ContainerInventoryHistoryEntity> inventories = containerInventoryHistoryService.inquireTallyingContainerInventoryList(tallyingId);
		for (ContainerInventoryHistoryEntity inventory : inventories) {
			if (!inventory.getTallyingState()) {
				throw new BusinessException("该理货任务中还有未完成的货箱");
			}
			if (inventory.validateAbnormal() && (inventory.getAbnormalState() == AbnormalStateEnum.UNKNOWN || inventory.getAbnormalState() == null)) {
				throw new BusinessException("该理货任务中还有异常的货箱未上报异常信息");
			}
		}
		TallyingEntity tallying = tallyingService.inquireTallyingDetail(tallyingId);
		tallying.setTallyingState(TallyingStateEnum.ALREADY_TALLY);
		tallying.setFinishedFileUuid(finishedFileUuid);
		tallying.setFinishedDateTime(DateUtils.now());
		tallyingService.renovateTallying(tallying);
	}

	@Transactional
	@Override
	public void reportTallying(Long tallyingId) {
		TallyingEntity tallying = tallyingService.inquireTallying(tallyingId);
		if (TallyingStateEnum.ALREADY_TALLY != tallying.getTallyingState()) {
			throw new BusinessException("该理货任务还未完成,完成后才能上报");
		}
		tallying.setTallyingState(TallyingStateEnum.ALREADY_REPORT);
		tallyingService.renovateTallying(tallying);

		// 上报时将理货History信息合并至箱信息中 一个任务一个箱
		RecieveNoticeEntity recieveNotice = recieveNoticeService.inquireRecieveNoticeDetail(tallying.getRecieveNoticeId());
		List<ContainerInventoryHistoryEntity> histories = containerInventoryHistoryService.inquireTallyingContainerInventoryList(tallyingId);
		ContainerInventoryHistoryEntity history = histories.get(0);
		ContainerInventoryEntity inventory = null;
		ContainerInventoryTallyEntity tally = null;

		if (BulkstockSourceEnum.REPEAT == recieveNotice.getBulkstockSource()) {
			if (history.getInventoryId() == null) { // 已存在箱信息
				throw new BusinessException("再次理货原箱ID丢失,数据错误");
			}
			inventory = containerInventoryService.inquireContainerInventory(history.getInventoryId());
			history.setFinanceId(inventory.getFinanceId());
			history.setFinanceNumber(inventory.getFinanceNumber());
			history.setEnterpriseId(inventory.getEnterpriseId());
			history.setEnterpriseName(inventory.getEnterpriseName());
			BeanUtils.copyProperties(history, inventory);
			inventory.setContainerSource(recieveNotice.getBulkstockSource());
			inventory.setReplenishCreditId(recieveNotice.getReplenishCreditId());
			inventory.setExchangePickupId(recieveNotice.getExchangePickupId());
			inventory.setSupervisionState(SupervisionStateEnum.ALREADY_REPORT);
			containerInventoryService.renovateContainerInventory(inventory);

			tally = containerInventoryTallyService.inquireContainerInventoryTally(history.getInventoryId());
		} else {
			inventory = new ContainerInventoryEntity();
			BeanUtils.copyProperties(history, inventory);
			inventory.setContainerSource(recieveNotice.getBulkstockSource());
			inventory.setReplenishCreditId(recieveNotice.getReplenishCreditId());
			inventory.setExchangePickupId(recieveNotice.getExchangePickupId());
			inventory.setSupervisionState(SupervisionStateEnum.ALREADY_REPORT);
			ContainerInventoryEntity exist = containerInventoryService.inquireContainerInventory(inventory.getWaybillNumber(), inventory.getCaseNumber());
			if (exist != null) {
				throw new BusinessException("系统中已存在该货箱");
			}
			containerInventoryService.createContainerInventory(inventory);
			
			//加锁
			if (1L == inventory.getLogisticsCompanyInfoId()) {
				LOG.info("理货加锁========");
				HandleSuitcaseResult result = new HandleSuitcaseResult();
				result = financeApplicationActionApiImpl.goldLocked(inventory.getInventoryId());
				FinanceContainerLogEntity fcle = new FinanceContainerLogEntity();
				fcle.setInventoryId(inventory.getInventoryId());
				fcle.setOperator(FinanceSessionContext.getAccountFullName());
				if (result != null) {
					fcle.setRemark("加锁 " + result.getMessage());
				} else {
					fcle.setRemark("加锁失败");
				}
				financeContainerLogService.createFinanceContainerLog(fcle);
			}
		}
		if (tally == null) {
			tally = new ContainerInventoryTallyEntity();
			BeanUtils.copyProperties(history, tally);
			tally.setInventoryId(inventory.getInventoryId());
			containerInventoryTallyService.createContainerInventoryTally(tally);
		} else {
			BeanUtils.copyProperties(history, tally);
			containerInventoryTallyService.renovateContainerInventoryTally(tally);
		}
		// 将货物信息合并至箱货信息中
		List<ContainerBulkstockHistoryEntity> bulkstockList = containerBulkstockHistoryService.inquireTallyingContainerBulkstockList(tallyingId);
		for (ContainerBulkstockHistoryEntity bulkstock : bulkstockList) {
			ContainerBulkstockEntity cbe = null;
			if (bulkstock.getContainerBulkstockId() != null) {
				cbe = containerBulkstockService.inquireContainerBulkstock(bulkstock.getContainerBulkstockId());
				if (!inventory.getInventoryId().equals(cbe.getInventoryId())) {
					throw new BusinessException("数据错误,货物的装箱ID与当前箱ID不匹配");
				}
				if (!bulkstock.getBulkstockId().equals(cbe.getBulkstockId())) {
					throw new BusinessException("要求理货货物信息与当前货物信息不匹配");
				}
				cbe.setTallyingId(tallyingId);
				cbe.setTrayNumber(bulkstock.getTrayNumber());
				cbe.setPlannedQuantity(bulkstock.getPlannedQuantity());
				cbe.setPlannedVolume(bulkstock.getPlannedVolume());
				cbe.setPlannedWeight(bulkstock.getPlannedWeight());
				cbe.setQuantity(bulkstock.getQuantity());
				cbe.setVolume(bulkstock.getVolume());
				cbe.setWeight(bulkstock.getWeight());
				cbe.setValuationQuantity(bulkstock.getValuationQuantity());
				cbe.setAbnormal(bulkstock.getAbnormal());
				cbe.setAbnormalComment(bulkstock.getAbnormalComment());
				cbe.setFilesUuid(bulkstock.getFilesUuid());
				containerBulkstockService.renovateContainerBulkstock(cbe);
			} else {
				cbe = new ContainerBulkstockEntity();
				BeanUtils.copyProperties(bulkstock, cbe);
				cbe.setInventoryId(inventory.getInventoryId());
				cbe.setTallyingId(tallyingId);
				containerBulkstockService.createContainerBulkstock(cbe);
			}
		}

		// 项目状态更新
		FinanceApplicationEntity financeEntity = financeApplicationService.inquireFinanceApplicationEntity(tallying.getFinanceId());
		financeEntity.setFinanceState(FinanceStateEnum.INSPECTIONED);
		financeEntity.setReceiveCreateDatetime(null);
		financeEntity.setSupervisionCreateDatetime(DateUtil.now());
		financeApplicationService.renovateFinanceApplication(financeEntity);

		// 项目动态
		FinanceProcessEntity processEntity = FinanceProcessCastor.fromFinanceRecieveProcess(tallying);
		if (!LongUtils.isPrimaryKey(processEntity.getProcessId())) {
			financeProcessService.createFinanceProcess(processEntity);
		} else {
			financeProcessService.renovateFinanceProcess(processEntity);
		}
		processEntity.getCurrentDetail().setProcessId(processEntity.getProcessId());
		financeProcessDetailService.createFinanceProcessDetail(processEntity.getCurrentDetail());
	}

	@Transactional
	@Override
	public void receiveConfirmTallying(Long[] inventoryIds, Date receiveConfirmCreateTime) {
		List<ContainerInventoryEntity> inventories = containerInventoryService.inquireContainerInventoryList(inventoryIds);
		Long financeId = inventories.get(0).getFinanceId();
		ContainerInventoryEntity financeContainer = null; // 监管尾箱
		for (ContainerInventoryEntity inventory : inventories) {
			if (SupervisionStateEnum.ALREADY_REPORT != inventory.getSupervisionState()) {
				throw new BusinessException("货箱" + inventory.getCaseNumber() + "不允许重复确认收货");
			}
			if (!financeId.equals(inventory.getFinanceId())) {
				throw new BusinessException("只能合并提交同一融资项目下的箱信息");
			}
		}
		for (ContainerInventoryEntity inventory : inventories) {
			if (receiveConfirmCreateTime == null) {
				inventory.setReceiveConfirmCreateTime(DateUtil.now());
			} else {
				inventory.setReceiveConfirmCreateTime(receiveConfirmCreateTime);
			}

			inventory.setSupervisionState(SupervisionStateEnum.DELIVERY_SURE);
			if (BulkstockSourceEnum.FINANCE == inventory.getContainerSource()) { // 融资来源货物装箱信息
				financeContainer = inventory;
			} else if (BulkstockSourceEnum.PICKUP == inventory.getContainerSource()) { // 提货来源装箱信息
				processPickupBulkstockAcceptance(inventory);
			} else if (BulkstockSourceEnum.CREDIT == inventory.getContainerSource()) { // 补货来源装箱信息
				processCreditBulkstockAcceptance(inventory);
			} else if (BulkstockSourceEnum.REPEAT == inventory.getContainerSource()) {
				if (inventory.getReplenishCreditId() == null && inventory.getExchangePickupId() == null) { // 融资二次理货
					financeContainer = inventory;
				}
			}
			containerInventoryService.renovateContainerInventory(inventory);

			FinanceContainerLogEntity fcle = new FinanceContainerLogEntity();
			fcle.setInventoryId(inventory.getInventoryId());
			fcle.setOperator(FinanceSessionContext.getAccountFullName());
			fcle.setRemark("收货确认");
			financeContainerLogService.createFinanceContainerLog(fcle);
		}
		if (financeContainer != null) {
			//			processFinanceBulkstock(financeContainer);
		}
	}

	@Transactional
	@Override
	public void superviseTallying(Long[] inventoryIds, Date superviseTallyingCreateTime) {
		ContainerInventoryEntity containerInventory = containerInventoryService.inquireContainerInventory(inventoryIds[0]);
		Long financeId = containerInventory.getFinanceId();
		FinanceContainerEntity container = financeContainerService.inquireFinanceContainer(financeId);
		FinanceApplicationEntity finance = financeApplicationService.inquireFinanceApplicationEntity(financeId);
		if (ProductTypeEnum.FREIGHT_FACTORING == finance.getProductType() || ProductTypeEnum.PROXY_SALE == finance.getProductType() || ProductTypeEnum.PURCHASING_STORAGE == finance.getProductType() || ProductTypeEnum.MANIFEST_PLEDGE == finance.getProductType()) {
			if (container == null) {
				container = new FinanceContainerEntity();
				container.setFinanceId(financeId);
				container.setEnterpriseId(finance.getEnterpriseId());
				container.setEnterpriseName(finance.getEnterpriseName());
				container.setFinanceNumber(finance.getFinanceNumber());
				List<ContainerInventoryEntity> inventories = containerInventoryService.inquireSupervisionFinanceAmountList(financeId);
				container.setCaseQuantity(inventories.size());
				financeContainerService.createFinanceContainer(container);
			} else {
				List<ContainerInventoryEntity> inventories = containerInventoryService.inquireSupervisionFinanceAmountList(financeId);
				container.setCaseQuantity(inventories.size());
				financeContainerService.renovateFinanceContainer(container);
			}
		} else if (container == null ) {
			throw new BusinessException("订舱信息为空,请填写订舱信息");
		} else if (container.getCaseQuantity() == null || container.getCaseQuantity() <= 0) {
			throw new BusinessException("订舱信息中订舱总箱量未填写,请填写订舱总箱量信息");
		}
		if (superviseTallyingCreateTime == null) {
			superviseContainerInventory(inventoryIds, false, DateUtil.now());
		} else {
			superviseContainerInventory(inventoryIds, false, superviseTallyingCreateTime);
		}
		//消息推送-合同上传
		SendLetterMessage.sendLetterMessage("financeContractManage_1", String.format(tmp, finance.getEnterpriseName(), finance.getFinanceNumber(), "合同上传"));
	}

	@Override
	public TallyingDetail inquireTallyingDetail(Long tallyingId) {
		TallyingEntity entity = tallyingService.inquireTallying(tallyingId);
		return TallyingDeliveryCastor.toTallyingDetail(entity);
	}

	@Override
	public PageList<TallyingLineInfo> inquireTallyingPageList(String waybillNumber, String caseNumber, Long[] tallyingIds, Long financeId, Long recieveNoticeId, Long logisticsCompanyId, String tallyingNumber, Long clerkId, Integer[] tallyingState, PageCriteria page) {
		List<Long> tallyingId = containerInventoryHistoryService.inquireTallyingIdsFromContainerInventory(waybillNumber, caseNumber);
		PageList<TallyingEntity> pageList = tallyingService.inquireTallyingPageList(tallyingId.toArray(new Long[tallyingId.size()]), financeId, recieveNoticeId, logisticsCompanyId, tallyingNumber, clerkId, tallyingState, Boolean.TRUE, page);
		PageList<TallyingLineInfo> resultList = new PageList<TallyingLineInfo>(page, pageList.getTotalRecordCount());
		for (TallyingEntity entity : pageList) {
			resultList.add(TallyingDeliveryCastor.toTallyingLineInfo(entity));
		}
		return resultList;
	}

	@Override
	public PageList<TallyingLineInfo> inquireClerkTallyingPageList(Integer[] tallyingState, Boolean sort, PageCriteria page) {
		Long logisticsCompanyId = FinanceSessionContext.getCompanyId();
		Long clerkId = FinanceSessionContext.getClerkId();
		PageList<TallyingEntity> pageList = tallyingService.inquireTallyingPageList(null, null, null, logisticsCompanyId, null, clerkId, tallyingState, sort, page);
		PageList<TallyingLineInfo> resultList = new PageList<TallyingLineInfo>(page, pageList.getTotalRecordCount());
		for (TallyingEntity entity : pageList) {
			resultList.add(TallyingDeliveryCastor.toClerkTallyingLineInfo(entity));
		}
		return resultList;
	}

	@Override
	public SupervisionConfirmationDetail inquireSupervisionConfirmationDetail(Long confirmationId) {
		SupervisionConfirmationEntity supervisionConfirmation = supervisionConfirmationService.inquireSupervisionConfirmation(confirmationId);
		return TallyingDeliveryCastor.toSupervisionConfirmationDetail(supervisionConfirmation);
	}

	// ========================================================================================================================//
	// 检查是否有超额配送
	private void validateDeliveryInventory(DeliveryNoticeEntity deliveryNotice, Long[] inventoryIds) {
		List<ContainerInventoryEntity> inventories = containerInventoryService.inquireWaitDeliveryBulkstockInventoryList(deliveryNotice);
		for (Long inventoryId : inventoryIds) {
			boolean validate = false;
			for (ContainerInventoryEntity cie : inventories) {
				LOG.debug(inventoryId.longValue() + ":" + cie.getInventoryId().longValue());
				if (inventoryId.longValue() == cie.getInventoryId().longValue()) {
					validate = true;
				}
			}
			if (!validate) {
				throw new BusinessException("配送货箱不在可提范围内,无法配送货物");
			}
		}
		// 提货货物信息
		List<PickupBulkstockEntity> bulkstockEntities = pickupBulkstockService.inquirePickupBulkstockList(deliveryNotice.getPickupId());
		Map<Long, BigDecimal> pickupBulkstocks = new HashMap<>();
		for (PickupBulkstockEntity pbe : bulkstockEntities) {
			BigDecimal quantity = pickupBulkstocks.get(pbe.getBulkstockId());
			if (quantity == null) {
				quantity = BigDecimal.ZERO;
			}
			pickupBulkstocks.put(pbe.getBulkstockId(), quantity.add(pbe.getQuantity()));
		}
		// 已发送配送任务的所有货物信息 + 当前配送货箱的货物信息
		inventories = containerInventoryService.inquirePickupContainerInventoryList(deliveryNotice.getPickupId());
		Set<Long> _inventoryIds = CollectionUtils.convertSet(inventoryIds);
		for (ContainerInventoryEntity cie : inventories) {
			_inventoryIds.add(cie.getInventoryId());
		}
		List<ContainerBulkstockEntity> bulkstockList = containerBulkstockService.inquireContainerBulkstockList(_inventoryIds.toArray(new Long[_inventoryIds.size()]));
		Map<Long, BigDecimal> deliveryBulkstocks = new HashMap<>();
		for (ContainerBulkstockEntity cbe : bulkstockList) {
			BigDecimal quantity = deliveryBulkstocks.get(cbe.getBulkstockId());
			if (quantity == null) {
				quantity = BigDecimal.ZERO;
			}
			deliveryBulkstocks.put(cbe.getBulkstockId(), quantity.add(cbe.getQuantity()));
		}
		for (Entry<Long, BigDecimal> entry : deliveryBulkstocks.entrySet()) {
			BigDecimal pickupQuantity = pickupBulkstocks.get(entry.getKey());
			if (pickupQuantity == null || pickupQuantity.intValue() < entry.getValue().intValue()) {
				throw new BusinessException("配送货物超过所提货物数量,无法配送货物");
			}
		}
	}

	private void completeDelivery(DeliveryEntity delivery, Long[] inventoryIds) {
		List<ContainerInventoryEntity> inventories = containerInventoryService.inquireContainerInventoryList(inventoryIds);
		for (ContainerInventoryEntity cie : inventories) {
			if (cie.getDeliveryId() != null) {
				continue;
			}
			cie.setPickupId(delivery.getPickupId());
			cie.setDeliveryNoticeId(delivery.getDeliveryNoticeId());
			cie.setDeliveryId(delivery.getDeliveryId());
			cie.setDeliveryCompanyId(delivery.getLogisticsCompanyId());
			containerInventoryService.renovateContainerInventory(cie);

			PickupInventoryEntity pickupInventory = pickupInventoryService.inquirePickupInventory(delivery.getPickupId(), cie.getInventoryId());
			if (pickupInventory == null) {
				pickupInventory = new PickupInventoryEntity();
				pickupInventory.setInventoryId(cie.getInventoryId());
				pickupInventory.setPickupId(delivery.getPickupId());
				pickupInventoryService.createPickupInventory(pickupInventory);
			}
		}
	}

	@Transactional
	@Override
	public String createDelivery(Long deliveryNoticeId, Long clerkId, String clerkName, String clerkMobile, Long[] inventoryIds) {
		if (inventoryIds == null || inventoryIds.length == 0) {
			throw new BusinessException("配送的货箱未选择");
		}
		DeliveryNoticeEntity deliveryNotice = deliveryNoticeService.inquireDeliveryNoticeDetail(deliveryNoticeId);
		validateDeliveryInventory(deliveryNotice, inventoryIds);

		DeliveryEntity delivery = TallyingDeliveryCastor.fromDelivery(deliveryNotice, clerkId, clerkName, clerkMobile);
		Long deliveryId = deliveryService.createDelivery(delivery);
		completeDelivery(delivery, inventoryIds);

		// 项目动态
		FinanceProcessDetailEntity processDetailEntity = FinanceProcessCastor.fromFinancePickupDeliveryProcessDetail(delivery);
		financeProcessDetailService.createFinanceProcessDetail(processDetailEntity);
		return deliveryId.toString();
	}

	@Transactional
	@Override
	public void updateDelivery(Long deliveryId, Long clerkId, String clerkName, String clerkMobile, Long[] inventoryIds) {
		DeliveryEntity persist = deliveryService.inqureDelivery(deliveryId);
		if (DeliveryStateEnum.REJECT != persist.getDeliveryState() && DeliveryStateEnum.WAIT_CONFIRM != persist.getDeliveryState()) {
			throw new BusinessException("配送任务已经确认不允许修改");
		}
		DeliveryNoticeEntity deliveryNotice = deliveryNoticeService.inquireDeliveryNoticeDetail(persist.getDeliveryNoticeId());
		validateDeliveryInventory(deliveryNotice, inventoryIds);

		DeliveryEntity delivery = TallyingDeliveryCastor.fromDelivery(deliveryNotice, clerkId, clerkName, clerkMobile);
		delivery.setDeliveryId(deliveryId);
		delivery.setDeliveryState(DeliveryStateEnum.WAIT_CONFIRM);
		deliveryService.updateDelivery(delivery);
		// 清除原有数据
		List<ContainerInventoryEntity> inventories = containerInventoryService.inquireDeliveryContainerInventoryList(deliveryId);
		for (ContainerInventoryEntity cie : inventories) {
			cie.setDeliveryId(null);
			cie.setDeliveryCompanyId(null);
			containerInventoryService.renovateContainerInventory(cie);
		}
		completeDelivery(delivery, inventoryIds);
	}

	@Transactional
	@Override
	public void confirmDelivery(Long deliveryId) {
		DeliveryEntity persist = deliveryService.inqureDelivery(deliveryId);
		persist.setDeliveryState(DeliveryStateEnum.ACCEPT);
		deliveryService.renovateDelivery(persist);
	}

	@Transactional
	@Override
	public void rejectDelivery(Long deliveryId) {
		DeliveryEntity persist = deliveryService.inqureDelivery(deliveryId);
		persist.setDeliveryState(DeliveryStateEnum.REJECT);
		deliveryService.renovateDelivery(persist);
	}

	private void handlesign(ContainerInventoryEntity inventory, ContainerInventorySignEntity sign, String signRemark, String signAddress, BigDecimal signLongitude, BigDecimal signLatitude, String signPreFile, String signSuffixFile) {
		PickupApplicationEntity pickup = pickupApplicationService.inquirePickupApplication(inventory.getPickupId());
		if (ApplicationStateEnum.RELEASE == pickup.getApplicationState()) {
			pickup.setDeliveryNoticeCreateDateTime(null);
			pickupApplicationService.renovatePickupApplication(pickup);
		}
		inventory.setSignState(Boolean.TRUE);
		inventory.setSignDateTime(DateUtil.now());
		inventory.setSupervisionRelieveCreateTime(DateUtil.now());

		containerInventoryService.renovateContainerInventory(inventory);

		sign.setInventoryId(inventory.getInventoryId());
		sign.setSignAccountId(FinanceSessionContext.getAccountId());
		sign.setSignAccountor(FinanceSessionContext.getAccountFullName());
		sign.setSignAddress(signAddress);
		sign.setSignLatitude(signLatitude);
		sign.setSignLongitude(signLongitude);
		sign.setSignPreFile(signPreFile);
		sign.setSignSuffixFile(signSuffixFile);
		sign.setSignRemark(signRemark);
		containerInventorySignService.createContainerInventorySign(sign);

		// 更新已提数量
		List<ContainerBulkstockEntity> bulkstocks = containerBulkstockService.inquireContainerBulkstockList(inventory.getInventoryId());
		for (ContainerBulkstockEntity cbe : bulkstocks) {
			PickupBulkstockEntity pickupBulkstock = pickupBulkstockService.inquirePickupBulkstock(inventory.getPickupId(), cbe.getBulkstockId());
			if (pickupBulkstock != null) {
				pickupBulkstock.setPickup(pickupBulkstock.getPickup().add(cbe.getQuantity()));
				pickupBulkstockService.renovatePickupBulkstock(pickupBulkstock);
			}
		}
		financeBulkstockService.calculatePickupFinanceBulkstock(inventory.getFinanceId());
		if (inventory.validateAbnormal()) {
			financeBulkstockService.calculateIncustodyFinanceBulkstock(inventory.getFinanceId());
			financeBulkstockService.calculateAbnormalFinanceBulkstock(inventory.getFinanceId());
		}
		// 更新放货通知
		DeliveryNoticeEntity deliveryNotice = deliveryNoticeService.inquireDeliveryNoticeDetail(inventory.getDeliveryNoticeId());
		deliveryNotice.setNoticeState(NoticeStateEnum.FINISHED);
		List<PickupBulkstockEntity> pickupBulkstockList = pickupBulkstockService.inquirePickupBulkstockList(inventory.getPickupId());
		for (PickupBulkstockEntity pbe : pickupBulkstockList) {
			if (pbe.getPickup().compareTo(pbe.getQuantity()) < 0) {
				deliveryNotice.setNoticeState(NoticeStateEnum.CONFIRMED);
				break;
			}
		}
		if (NoticeStateEnum.FINISHED == deliveryNotice.getNoticeState()) {
			deliveryNoticeService.updateDeliveryNotice(deliveryNotice);
		}
		// 更新配送任务
		DeliveryEntity delivery = deliveryService.inqureDelivery(inventory.getDeliveryId());
		delivery.setDeliveryState(DeliveryStateEnum.FINISHED);
		List<ContainerInventoryEntity> inventoryList = containerInventoryService.inquireDeliveryContainerInventoryList(inventory.getDeliveryId());
		for (ContainerInventoryEntity cie : inventoryList) {
			if (!cie.getSignState()) {
				delivery.setDeliveryState(DeliveryStateEnum.ACCEPT);
				break;
			}
		}
		if (DeliveryStateEnum.FINISHED == delivery.getDeliveryState()) {
			deliveryService.renovateDelivery(delivery);
		}
		// 更新融资状态
		FinanceApplicationEntity financeEntity = financeApplicationService.inquireFinanceApplicationEntity(inventory.getFinanceId());
		financeEntity.setFinanceState(FinanceStateEnum.SIGN);
		financeApplicationService.renovateFinanceApplication(financeEntity);
		// 项目动态
		FinanceProcessEntity pickupProcess = FinanceProcessCastor.fromFinancePickupSignProcess(inventory);
		FinanceProcessEntity arriveProcess = pickupProcess.getParentProcess();
		financeProcessService.renovateFinanceProcess(arriveProcess);
		financeProcessService.renovateFinanceProcess(pickupProcess);
		FinanceProcessDetailEntity currentDetail = pickupProcess.getCurrentDetail();
		financeProcessDetailService.createFinanceProcessDetail(currentDetail);
	}

	@Transactional
	@Override
	public void signContainerInventory(Long inventoryId, String signRemark, String signAddress, BigDecimal signLongitude, BigDecimal signLatitude, String signPreFile, String signSuffixFile) {
		ContainerInventoryEntity inventory = containerInventoryService.inquireContainerInventory(inventoryId);
		ContainerInventorySignEntity sign = new ContainerInventorySignEntity();
		handlesign(inventory, sign, signRemark, signAddress, signLongitude, signLatitude, signPreFile, signSuffixFile);
	}

	@Override
	@Transactional
	public void syncOutboundNotifyInfo(String caseNumber, String fileNameArray, String operator, String soundRecord, String remark) {
		ContainerInventoryEntity inventory = containerInventoryService.inquireContainerInventory(null, caseNumber);
		if (inventory == null) {
			throw new BusinessException("该货箱不存在！");
		}
		inventory.setSignState(Boolean.TRUE);
		inventory.setSignDateTime(DateUtil.now());
		inventory.setSupervisionRelieveCreateTime(DateUtil.now());
		containerInventoryService.renovateContainerInventory(inventory);

		StringBuffer sb = new StringBuffer();
		String[] fa = fileNameArray.split(",");
		for (int j = 0; j < fa.length; j++) {
			LOG.info("fuleUrl:" + ConfigPropertites.getProperties("finance.fileUrl.service") + fa[j]);
			InputStream is = HttpUtils.returnBitMap(ConfigPropertites.getProperties("finance.fileUrl.service") + fa[j]);
			if (is != null) {
				FileEntry fe = transferService.uploadFile(fa[j], is);
				sb = sb.append(fe.getFileUuid()).append(",");
			}
		}

		ContainerInventorySignEntity sign = new ContainerInventorySignEntity();
		sign.setInventoryId(inventory.getInventoryId());
		sign.setSignPreFile(sb.toString());
		sign.setSignSuffixFile(sb.toString());
		sign.setSignRemark(remark);
		sign.setSignAccountor(operator);

		sb = new StringBuffer();
		InputStream is1 = HttpUtils.returnBitMap(ConfigPropertites.getProperties("finance.fileUrl.service") + soundRecord);
		if (is1 != null) {
			FileEntry fe = transferService.uploadFile(soundRecord, is1);
			sb = sb.append(fe.getFileUuid()).append(",");
		}
		sign.setSignSoundRecorde(sb.toString());
		containerInventorySignService.createContainerInventorySign(sign);
	}

	@Transactional
	@Override
	public void signAbnormalContainerInventory(Long inventoryId, String signRemark, String signAddress, BigDecimal signLongitude, BigDecimal signLatitude, String signPreFile, String signSuffixFile, Integer abnormalState,
			String signSoundRecorde, String signAbnormalFile) {
		ContainerInventoryEntity inventory = containerInventoryService.inquireContainerInventory(inventoryId);
		inventory.setAbnormal(Boolean.FALSE);
		inventory.setAbnormalType(AbnormalTypeEnum.SIGN);
		inventory.setAbnormalState(AbnormalStateEnum.valueOf(abnormalState));
		inventory.setDetainedState(false);

		ContainerInventorySignEntity sign = new ContainerInventorySignEntity();
		sign.setSignAbnormalFile(signAbnormalFile);
		sign.setSignSoundRecorde(signSoundRecorde);
		handlesign(inventory, sign, signRemark, signAddress, signLongitude, signLatitude, signPreFile, signSuffixFile);

		// 异常处理
		AbnormalEntity abnormal = AbnormalCastor.fromDeliveryInventory(sign, inventory);
		Long abnormalId = abnormalService.createAbnormal(abnormal);
		AbnormalInventoryEntity abnormalInventory = new AbnormalInventoryEntity();
		abnormalInventory.setInventoryId(inventoryId);
		abnormalInventory.setAbnormalId(abnormalId);
		abnormalInventoryService.createAbnormalInventory(abnormalInventory);
	}

	@Override
	public DeliveryDetail inquireDeliveryDetail(Long deliveryId) {
		DeliveryEntity entity = deliveryService.inqureDelivery(deliveryId);
		return TallyingDeliveryCastor.toDeliveryDetail(entity);
	}

	@Override
	public PageList<DeliveryLineInfo> inquireDeliveryPageList(Long[] deliveryIds, Long financeId, String financeNumber, Long deliveryNoticeId, Long logisticsCompanyId, Long clerkId, PageCriteria page) {
		PageList<DeliveryEntity> pageList = deliveryService.inqureDeliveryPageList(deliveryIds, financeId, financeNumber, deliveryNoticeId, logisticsCompanyId, clerkId, page);
		PageList<DeliveryLineInfo> resultList = new PageList<>(page, pageList.getTotalRecordCount());
		for (DeliveryEntity entity : pageList) {
			resultList.add(TallyingDeliveryCastor.toDeliveryLineInfo(entity));
		}
		return resultList;
	}

	@Transactional
	@Override
	public boolean createSupervisionRelieve(Long inventoryId, String relieveRemark) {
		ContainerInventoryEntity inventory = containerInventoryService.inquireContainerInventory(inventoryId);
		inventory.setSupervisionState(SupervisionStateEnum.RELIEVE_SUPERVISE);
		containerInventoryService.renovateContainerInventory(inventory);
		// 更新在押数量
		financeBulkstockService.calculateIncustodyFinanceBulkstock(inventory.getFinanceId());

		ContainerInventoryRelieveEntity relieve = new ContainerInventoryRelieveEntity();
		relieve.setInventoryId(inventoryId);
		relieve.setRelieveAccountId(FinanceSessionContext.getAccountId());
		relieve.setRelieveAccountor(FinanceSessionContext.getAccountFullName());
		relieve.setRelieveRemark(relieveRemark);
		containerInventoryRelieveService.createContainerInventoryRelieve(relieve);
		// 项目动态
		FinanceProcessEntity processEntity = FinanceProcessCastor.fromFinanceRelieveProcess(inventory, false);
		if (!LongUtils.isPrimaryKey(processEntity.getProcessId())) {
			financeProcessService.createFinanceProcess(processEntity);
		} else {
			financeProcessService.renovateFinanceProcess(processEntity);
		}
		processEntity.getCurrentDetail().setProcessId(processEntity.getProcessId());
		financeProcessDetailService.createFinanceProcessDetail(processEntity.getCurrentDetail());
		// 判断货物是否全都通知收货,并且全都监管解除
		boolean finished = true;
		List<FinanceBulkstockEntity> bulkstockList = financeBulkstockService.inquireFinanceBulkstockList(inventory.getFinanceId());
		for (FinanceBulkstockEntity fbe : bulkstockList) {
			if (fbe.getQuantity().compareTo(fbe.getRecieve()) > 0 || fbe.getAbnormal().compareTo(BigDecimal.ZERO) > 0 || fbe.getQuantity().compareTo(fbe.getSupervision()) > 0 || fbe.getIncustody().compareTo(BigDecimal.ZERO) > 0) { // 部分货物还未下发收货通知|货物出现异常||货物未全部解质
				finished = false;
				break;
			}
		}

		FinanceContainerLogEntity fcle = new FinanceContainerLogEntity();
		fcle.setInventoryId(inventory.getInventoryId());
		fcle.setOperator(FinanceSessionContext.getAccountFullName());
		fcle.setRemark("解除监管");
		financeContainerLogService.createFinanceContainerLog(fcle);


		return finished;
	}

	@Transactional
	@Override
	@SuppressWarnings("unchecked")
	public SyncTallyMessage syncTally(String tallyjson, String sign) { // 同步过来的理货信息存在 首次理货/再次理货
		LOG.debug("理货同步数据:" + tallyjson);
		SyncTallyMessage message = new SyncTallyMessage();
		Class<TallySyncParams> genicType = TallySyncParams.class;
		Class<ArrayList<TallySyncParams>> type = (Class<ArrayList<TallySyncParams>>) new ArrayList<TallySyncParams>().getClass();
		Collection<TallySyncParams> params = JSON.toBeanSet(tallyjson, type, genicType);
		for (TallySyncParams param : params) {
			MessageDetail detail = new MessageDetail();
			detail.setCaseNumber(param.getCaseNumber());
			detail.setWaybillNumber(param.getWaybillNumber());
			try {
				// 生成理货任务
				TallyingEntity tallying = TallyingDeliveryCastor.fromSyncTally(param);
				if (LongUtils.isPrimaryKey(tallying.getTallyingId())) {
					tallyingService.renovateTallying(tallying);
				} else {
					tallyingService.createTallying(tallying);
				}

				ContainerInventoryHistoryEntity cihe = tallying.getContainerInventoryHistory();
				if (LongUtils.isPrimaryKey(cihe.getInventoryHistoryId())) {
					containerInventoryHistoryService.renovateContainerInventory(cihe);
				} else {
					cihe.setTallyingId(tallying.getTallyingId());
					containerInventoryHistoryService.createContainerInventory(cihe);
				}
				RecieveNoticeEntity recieveNotice = recieveNoticeService.inquireNumberRecieveNotice(param.getRecieveNoticeNumber());
				ContainerInventoryEntity inventory = null;
				ContainerInventoryTallyEntity tally = null;
				if (BulkstockSourceEnum.REPEAT == recieveNotice.getBulkstockSource()) {
					if (cihe.getInventoryId() == null) { // 已存在箱信息
						throw new BusinessException("再次理货原箱ID丢失,数据错误");
					}
					inventory = containerInventoryService.inquireContainerInventory(cihe.getInventoryId());
					cihe.setFinanceId(inventory.getFinanceId());
					cihe.setFinanceNumber(inventory.getFinanceNumber());
					cihe.setEnterpriseId(inventory.getEnterpriseId());
					cihe.setEnterpriseName(inventory.getEnterpriseName());
					BeanUtils.copyProperties(cihe, inventory);
					inventory.setSupervisionState(SupervisionStateEnum.ALREADY_REPORT);
					containerInventoryService.renovateContainerInventory(inventory);

					tally = containerInventoryTallyService.inquireContainerInventoryTally(cihe.getInventoryId());
				} else {
					inventory = new ContainerInventoryEntity();
					BeanUtils.copyProperties(cihe, inventory);
					inventory.setContainerSource(recieveNotice.getBulkstockSource());
					inventory.setReplenishCreditId(recieveNotice.getReplenishCreditId());
					inventory.setExchangePickupId(recieveNotice.getExchangePickupId());
					inventory.setSupervisionState(SupervisionStateEnum.ALREADY_REPORT);
					containerInventoryService.createContainerInventory(inventory);

					tally = new ContainerInventoryTallyEntity();
				}
				if (tally == null) {
					tally = new ContainerInventoryTallyEntity();
					BeanUtils.copyProperties(cihe, tally);
					tally.setInventoryId(inventory.getInventoryId());
					containerInventoryTallyService.createContainerInventoryTally(tally);
				} else {
					BeanUtils.copyProperties(cihe, tally);
					containerInventoryTallyService.renovateContainerInventoryTally(tally);
				}
				// 将货物信息合并至箱货信息中
				ContainerBulkstockHistoryEntity cbhe = cihe.getContainerBulkstockHistories().get(0);
				ContainerBulkstockEntity cbe = null;
				if (cbhe.getContainerBulkstockId() != null) {
					cbe = containerBulkstockService.inquireContainerBulkstock(cbhe.getContainerBulkstockId());
					if (!inventory.getInventoryId().equals(cbe.getInventoryId())) {
						throw new BusinessException("数据错误,货物的装箱ID与当前箱ID不匹配");
					}
					if (!cbhe.getBulkstockId().equals(cbe.getBulkstockId())) {
						throw new BusinessException("要求理货货物信息与当前货物信息不匹配");
					}
					cbe.setTallyingId(tallying.getTallyingId());
					cbe.setTrayNumber(cbhe.getTrayNumber());
					cbe.setPlannedQuantity(cbhe.getPlannedQuantity());
					cbe.setPlannedVolume(cbhe.getPlannedVolume());
					cbe.setPlannedWeight(cbhe.getPlannedWeight());
					cbe.setQuantity(cbhe.getQuantity());
					cbe.setVolume(cbhe.getVolume());
					cbe.setWeight(cbhe.getWeight());
					cbe.setValuationQuantity(cbhe.getValuationQuantity());
					cbe.setAbnormal(cbhe.getAbnormal());
					cbe.setAbnormalComment(cbhe.getAbnormalComment());
					cbe.setFilesUuid(cbhe.getFilesUuid());
					containerBulkstockService.renovateContainerBulkstock(cbe);
				} else {
					cbe = new ContainerBulkstockEntity();
					BeanUtils.copyProperties(cbhe, cbe);
					cbe.setInventoryId(inventory.getInventoryId());
					cbe.setTallyingId(tallying.getTallyingId());
					containerBulkstockService.createContainerBulkstock(cbe);
				}
				detail.setSuccess(true);
				detail.setDescription("同步成功");
			} catch (BusinessException e) {
				e.printStackTrace();
				detail.setSuccess(false);
				detail.setDescription(e.getMessage());
			} catch (Exception e) {
				e.printStackTrace();
				detail.setSuccess(false);
				detail.setDescription("接口数据处理异常," + e.getMessage());
			} finally {
				message.getDetails().add(detail);
			}
		}
		return message;
	}

	@Override
	@Transactional
	public void syncLocalTallyContainer(Long inventoryHistoryId, String waybillNumber, String caseNumber) {
		List<ContainerInventoryHistoryEntity> exists = containerInventoryHistoryService.inquireLogisticsContainerInventoryList(waybillNumber, caseNumber);
		if (exists.isEmpty()) {
			throw new BusinessException("运单号[" + waybillNumber + "]下不存在箱号[" + caseNumber + "]");
		}
		ContainerInventoryHistoryEntity source = exists.get(0);
		if (!source.getTallyingState()) {
			throw new BusinessException("同步的箱还未完成理货");
		}
		ContainerInventoryHistoryEntity target = containerInventoryHistoryService.inquireContainerInventory(inventoryHistoryId);
		if (target.getTallyingState()) {
			throw new BusinessException("该箱已经存在理货信息");
		}
		RecieveNoticeEntity recieveNotice = recieveNoticeService.inquireRecieveNoticeDetail(target.getRecieveNoticeId());
		if (BulkstockSourceEnum.LOGISTICS == recieveNotice.getBulkstockSource()) {
			throw new BusinessException("物流方自理的箱信息无需同步");
		}
		TallyingEntity tallying = tallyingService.inquireTallying(target.getTallyingId());
		BeanUtils.copyProperties(source, target, "inventoryHistoryId", "inventoryId");
		target.setFinanceId(recieveNotice.getFinanceId());
		target.setFinanceNumber(recieveNotice.getFinanceNumber());
		target.setEnterpriseId(recieveNotice.getEnterpriseId());
		target.setEnterpriseName(recieveNotice.getEnterpriseName());
		target.setRecieveNoticeId(recieveNotice.getRecieveNoticeId());
		target.setTallyingId(tallying.getTallyingId());
		target.setTallyingCompanyId(tallying.getLogisticsCompanyId());
		target.setTallyingState(Boolean.TRUE);
		containerInventoryHistoryService.renovateContainerInventory(target);

		List<ContainerBulkstockHistoryEntity> targetBulkstocks = containerBulkstockHistoryService.inquireContainerHistoryBulkstockList(inventoryHistoryId);
		List<ContainerBulkstockHistoryEntity> sourceBulkstocks = containerBulkstockHistoryService.inquireContainerHistoryBulkstockList(source.getInventoryHistoryId());
		List<FinanceBulkstockEntity> financeBulkstocks = financeBulkstockService.inquireFinanceBulkstockList(recieveNotice.getFinanceId());
		for (ContainerBulkstockHistoryEntity p : sourceBulkstocks) {
			ContainerBulkstockHistoryEntity targetBulkstock = null;
			for (ContainerBulkstockHistoryEntity cbhe : targetBulkstocks) {
				if (cbhe.getBulkstockInfoId().equals(p.getBulkstockInfoId()) && ((p.getQuantity() != null && p.getQuantity().compareTo(BigDecimal.ZERO) > 0) || (p.getWeight() != null && p.getWeight().compareTo(BigDecimal.ZERO) > 0))) { // 货物与无融资理货中的货物一致
					targetBulkstock = cbhe;
					break;
				}
			}
			if (targetBulkstock == null) {
				FinanceBulkstockEntity financeBulkstock = null;
				for (FinanceBulkstockEntity fbe : financeBulkstocks) {
					if (fbe.getBulkstockInfoId().equals(p.getBulkstockInfoId())) { // 融资货物中
						financeBulkstock = fbe;
						break;
					}
				}
				if (financeBulkstock == null) {
					throw new BusinessException("箱信息中存在未融资货物[" + p.getBulkstockName() + "|" + p.getSpecification() + "]");
				}
				targetBulkstock = new ContainerBulkstockHistoryEntity();
				targetBulkstock.setInventoryHistoryId(target.getInventoryHistoryId());
				targetBulkstock.setTallyingId(target.getTallyingId());
				targetBulkstock.setFinanceId(target.getFinanceId());
				targetBulkstock.setBulkstockId(financeBulkstock.getBulkstockId());
				targetBulkstock.setBulkstockCategoryId(financeBulkstock.getBulkstockCategoryId());
				targetBulkstock.setBulkstockInfoId(financeBulkstock.getBulkstockInfoId());
				targetBulkstock.setBulkstockName(financeBulkstock.getBulkstockName());
				targetBulkstock.setSpecification(financeBulkstock.getSpecification());
				targetBulkstock.setUnit(financeBulkstock.getUnit());
				targetBulkstock.setMeasurement(financeBulkstock.getMeasurement());
				targetBulkstock.setBulkstockPrice(financeBulkstock.getBulkstockPrice());
				targetBulkstock.setEvaluatePrice(financeBulkstock.getEvaluatePrice());
				targetBulkstock.setFinancePrice(financeBulkstock.getFinancePrice());
			}
			targetBulkstock.setPlannedQuantity(targetBulkstock.existsPlannedQuantity() ? targetBulkstock.getPlannedQuantity() : p.getPlannedQuantity());
			targetBulkstock.setPlannedVolume(targetBulkstock.existsPlannedVolume() ? targetBulkstock.getPlannedVolume() : p.getPlannedVolume());
			targetBulkstock.setPlannedWeight(targetBulkstock.existsPlannedWeight() ? targetBulkstock.getPlannedWeight() : p.getPlannedWeight());
			targetBulkstock.setQuantity(p.getQuantity());
			targetBulkstock.setVolume(p.getVolume());
			targetBulkstock.setWeight(p.getWeight());
			targetBulkstock.setTrayNumber(p.getTrayNumber());
			targetBulkstock.setAbnormal(p.getAbnormal());
			targetBulkstock.setAbnormalComment(p.getAbnormalComment());
			targetBulkstock.setFilesUuid(p.getFilesUuid());
			if (MeasurementEnum.VOLUME == targetBulkstock.getMeasurement()) { // 体积计价
				if (targetBulkstock.getVolume() == null || targetBulkstock.getVolume().compareTo(BigDecimal.ZERO) <= 0) {
					throw new BusinessException("该商品以体积计价,理货体积不允许为空或小于0");
				}
				targetBulkstock.setValuationQuantity(targetBulkstock.getVolume());
			} else { // 重量计价
				if (targetBulkstock.getWeight() == null || targetBulkstock.getWeight().compareTo(BigDecimal.ZERO) <= 0) {
					throw new BusinessException("该商品以重量计价,理货重量不允许为空或小于0");
				}
				targetBulkstock.setValuationQuantity(targetBulkstock.getWeight());
			}
			if (LongUtils.isPrimaryKey(targetBulkstock.getBulkstockHistoryId())) {
				containerBulkstockHistoryService.renovateContainerBulkstock(targetBulkstock);
			} else {
				containerBulkstockHistoryService.createContainerBulkstock(targetBulkstock);
			}
		}
		for (ContainerBulkstockHistoryEntity cbhe : targetBulkstocks) {
			if (cbhe.getValuationQuantity() == null || cbhe.getValuationQuantity().compareTo(BigDecimal.ZERO) <= 0) { // 计划融资货物不存在
				throw new BusinessException("同步的理货数据中,不存在计划货物[" + cbhe.getBulkstockName() + "]");
			}
		}
	}

	@Override
	public TallySyncParams syncTallyResult() {
		return null;
	}

	@Transactional
	@Override
	@SuppressWarnings("unchecked")
	public SyncTallyMessage syncContainerSign(String signjson, String sign) {
		LOG.debug("签收同步数据:" + signjson);
		SyncTallyMessage message = new SyncTallyMessage();
		Class<SignSyncParams> genicType = SignSyncParams.class;
		Class<ArrayList<SignSyncParams>> type = (Class<ArrayList<SignSyncParams>>) new ArrayList<SignSyncParams>().getClass();
		Collection<SignSyncParams> params = JSON.toBeanSet(signjson, type, genicType);
		for (SignSyncParams param : params) {
			MessageDetail detail = new MessageDetail();
			detail.setCaseNumber(param.getCaseNumber());
			detail.setWaybillNumber(param.getWaybillNumber());
			try {
				ContainerInventoryEntity container = TallyingDeliveryCastor.fromSyncContainerSign(param);
				containerInventoryService.renovateContainerInventory(container);
				ContainerInventorySignEntity containerSign = container.getContainerInventorySign();
				containerInventorySignService.createContainerInventorySign(containerSign);
				detail.setSuccess(true);
				detail.setDescription("同步成功");
			} catch (BusinessException e) {
				e.printStackTrace();
				detail.setSuccess(false);
				detail.setDescription(e.getMessage());
			} catch (Exception e) {
				e.printStackTrace();
				detail.setSuccess(false);
				detail.setDescription("接口数据处理异常," + e.getMessage());
			} finally {
				message.getDetails().add(detail);
			}
		}
		return message;
	}

	@Override
	public SignSyncParams syncContainerSignResult() {
		return null;
	}

	@Override
	public DeliveryDetail inquireDeliveryDetailByCondition(Long deliveryId, String caseNumber, String waybillNumber) {
		DeliveryEntity entity = deliveryService.inqureDelivery(deliveryId);
		return TallyingDeliveryCastor.toDeliveryDetailByCondition(entity, caseNumber, waybillNumber);
	}

	@Override
	@Transactional
	public void reportBulkstockInfoFromWareHouse(String warehouseId, String warehouse, String cabinNumber,
			Long financeId, Long[] bulkstockInfoIds, BigDecimal[] quantities, BigDecimal[] volumes, BigDecimal[] weights, String[] imageNames, String receiptId, String[] storageLocation, String[] trayNumbers,  String facingSlip, String facingSlipNext) {
		if (bulkstockInfoIds == null || bulkstockInfoIds.length <= 0) {
			throw new BusinessException("货物不允许为空！");
		}
		ContainerInventoryEntity cie = new ContainerInventoryEntity();
		FinanceApplicationEntity finance = financeApplicationService.inquireFinanceApplicationEntity(financeId);
		cie.setAdjustment(BigDecimal.ZERO);
		cie.setCaseNumber(cabinNumber);
		cie.setContainerSource(BulkstockSourceEnum.FINANCE);
		cie.setTallyingState(Boolean.TRUE);
		cie.setType(1);
		cie.setFacingSlip(facingSlip);
		cie.setTallyDateTime(DateUtil.now());
		cie.setFinanceId(finance.getFinanceId());
		cie.setFinanceNumber(finance.getFinanceNumber());
		cie.setEnterpriseId(finance.getEnterpriseId());
		cie.setEnterpriseName(finance.getEnterpriseName());
		cie.setHarborDateTime(DateUtil.now());
		cie.setHarborState(Boolean.TRUE);
		cie.setEnabled(Boolean.TRUE);
		cie.setSupervisionState(SupervisionStateEnum.ALREADY_REPORT);
		cie.setReceiptId(receiptId);
		containerInventoryService.createContainerInventory(cie);

		//理货箱信息
		ContainerInventoryTallyEntity cite = new ContainerInventoryTallyEntity();
		cite.setInventoryId(cie.getInventoryId());
		StringBuffer sb1 = new StringBuffer();
		for (String sl : storageLocation) {
			sb1.append(sl).append(",");
		}
		if (sb1.length()>0) {
			sb1.deleteCharAt(sb1.length() - 1);
			cite.setTallyAddress(sb1.toString());
		}
		containerInventoryTallyService.createContainerInventoryTally(cite);

		List<FinanceBulkstockEntity> fbes = financeBulkstockService.inquireFinanceBulkstockList(financeId);
		for (int i = 0; i < bulkstockInfoIds.length; i ++) {
			ContainerBulkstockEntity cbe = new ContainerBulkstockEntity();
			BeanUtils.copyProperties(fbes.get(0), cbe);
			cbe.setInventoryId(cie.getInventoryId());
			cbe.setPlannedQuantity(quantities[i]);
			cbe.setPlannedVolume(volumes[i]);
			cbe.setPlannedWeight(weights[i]);
			cbe.setQuantity(quantities[i]);
			cbe.setVolume(volumes[i]);
			cbe.setTrayNumber(trayNumbers[i]);
			cbe.setWeight(weights[i]);
			cbe.setValuationQuantity(quantities[i]);
			String[] fileNameArray = imageNames[i].split(",");
			StringBuffer sb = new StringBuffer();

			for (int j = 0; j < fileNameArray.length; j++) {
				LOG.info("fuleUrl:" + ConfigPropertites.getProperties("finance.fileUrl.service") + fileNameArray[j]);
				InputStream is = HttpUtils.returnBitMap(ConfigPropertites.getProperties("finance.fileUrl.service") + fileNameArray[j]);
				if (is != null) {
					FileEntry fe = transferService.uploadFile(fileNameArray[j], is);
					sb = sb.append(fe.getFileUuid()).append(",");
				}
			}

			if (sb.length() > 0) {
				sb.deleteCharAt(sb.length() - 1);
			}
			cbe.setFilesUuid(sb.toString());

			containerBulkstockService.createContainerBulkstock(cbe);
		}
		finance.setFinanceState(FinanceStateEnum.INSPECTIONED);
		financeApplicationService.updateFinanceApplication(finance);
	}

	@Override
	public void submitContainerTallyingByUploadfile(Long recieveNoticeId, Long clerkId, String inventoryFile, String inventoryImage) {
		try {
			FileParseService fileParseService = ComponentFactory.loadClass(FileParseService.class);
//			BulkstockInfoService bulkstockInfoService = ComponentFactory.loadClass(BulkstockInfoService.class);
			List<List<String>> datas = fileParseService.parseExcel(inventoryFile, INVENTORY_TITLES);
			List<String> caseQueue = new ArrayList<>();
			List<String> bulkstockCaseQueue = new ArrayList<>();
			List<String> caseNumber = new ArrayList<>();
			List<String> waybillNumber = new ArrayList<>();
			List<String> caseSize = new ArrayList<>();
			List<Long> recieveNoticeDetailId = new ArrayList<>();
			List<Integer> caseQuantity = new ArrayList<>();
			List<String> trayNumber = new ArrayList<>();
			List<BigDecimal> plannedQuantity = new ArrayList<>();
			List<BigDecimal> plannedVolume = new ArrayList<>();
			List<BigDecimal> plannedWeight = new ArrayList<>();
			List<RecieveNoticeInventoryEntity> rnies = recieveNoticeInventoryService.inquireRecieveNoticeInventoryList(recieveNoticeId);
			for (int i = 0; i < datas.size(); i++) {
				List<String> l = datas.get(i);
				caseQueue.add(String.valueOf(i));
				bulkstockCaseQueue.add(String.valueOf(i));
				caseNumber.add(l.get(2));
				waybillNumber.add(l.get(3));
				trayNumber.add("");
				plannedQuantity.add(BigDecimal.ZERO);
				plannedVolume.add(BigDecimal.ZERO);
				plannedWeight.add(new BigDecimal(l.get(4)));
				recieveNoticeDetailId.add(rnies.get(0).getNoticeInventoryId());
				caseSize.add("20GP");
				caseQuantity.add(1);
			}

			TallyingParams tp = new TallyingParams();
			tp.setRecieveNoticeId(recieveNoticeId);
			tp.setClerkId(clerkId);
			tp.setWithCar(0);
			tp.setLimitDate(DateUtil.nextDay(DateUtil.now()));
			tp.setCaseNumber(caseNumber.toArray(new String[caseNumber.size()]));
			tp.setWaybillNumber(waybillNumber.toArray(new String[waybillNumber.size()]));
			tp.setCaseQueue(caseQueue.toArray(new String[caseQueue.size()]));
			tp.setBulkstockCaseQueue(bulkstockCaseQueue.toArray(new String[bulkstockCaseQueue.size()]));
			tp.setTrayNumber(trayNumber.toArray(new String[trayNumber.size()]));
			tp.setPlannedQuantity(plannedQuantity.toArray(new BigDecimal[plannedQuantity.size()]));
			tp.setPlannedVolume(plannedVolume.toArray(new BigDecimal[plannedVolume.size()]));
			tp.setPlannedWeight(plannedWeight.toArray(new BigDecimal[plannedWeight.size()]));
			tp.setRecieveNoticeDetailId(recieveNoticeDetailId.toArray(new Long[recieveNoticeDetailId.size()]));
			tp.setCaseSize(caseSize.toArray(new String[caseSize.size()]));
			tp.setCaseQuantity(caseQuantity.toArray(new Integer[caseQuantity.size()]));

			createTallying(tp);

			List<TallyingEntity> tes = tallyingService.inquireTallyingList(recieveNoticeId);
			for (TallyingEntity te : tes) {
				ContainerTallyingSubmitParams ctsp = new ContainerTallyingSubmitParams();
				TallyingDetail td = inquireTallyingDetail(te.getTallyingId());
				ctsp.setLogisticsCompanyInfoId(0L);
				ctsp.setAbnormal(1);
				ctsp.setTallyingId(te.getTallyingId());
				ctsp.setInventoryHistoryId(td.getContainerInventorys().get(0).getInventoryHistoryId());
				ctsp.setTallyExAbnormalState(1);
				ctsp.setCaseSize("20GP");
				ctsp.setFacingSlip("-");
				ctsp.setTallyAddress("-");
				ctsp.setWeight(new BigDecimal[]{td.getContainerInventorys().get(0).getContainerBulkstocks().get(0).getPlannedWeight()});
				ctsp.setQuantity(new BigDecimal[]{new BigDecimal(1)});
				ctsp.setVolume(new BigDecimal[]{BigDecimal.ZERO});
				ctsp.setRecieveNoticeDetailId(new Long[]{td.getContainerInventorys().get(0).getContainerBulkstocks().get(0).getRecieveNoticeDetailId()});
				ctsp.setBulkstockHistoryId(new Long[]{td.getContainerInventorys().get(0).getContainerBulkstocks().get(0).getBulkstockHistoryId()});
				ctsp.setCaseNumber(td.getContainerInventorys().get(0).getCaseNumber());
				ctsp.setWaybillNumber(td.getContainerInventorys().get(0).getWaybillNumber());
				ctsp.setBulkstockAbnormal(new Integer[]{1});
				FileEntry inventoryImageFile = transferService.inquireFileEntry(inventoryImage);
				FileEntry fe = readZipFile(ConfigPropertites.getProperties("UPLOAD_FILE_PATH") + inventoryImageFile.getRelativePath(), td.getContainerInventorys().get(0).getCaseNumber());
				if (fe != null) {
					ctsp.setTallyPreFile(fe.getFileUuid());
					ctsp.setTallySuffixFile(fe.getFileUuid());
					String[] s = fe.getFileName().split("/");
					String path = "";
					for (int i = 0; i < s.length -1; i++) {
						path += s[i] + "/";
					}
					FileEntry fe1 = readZipFile(ConfigPropertites.getProperties("UPLOAD_FILE_PATH") + inventoryImageFile.getRelativePath(), path + "bulkstock");
					if (fe1 != null) {
						ctsp.setFilesUuid(new String[]{fe1.getFileUuid()});
					} else {
						ctsp.setFilesUuid(new String[]{"-"});
					}
				} else {
					System.out.println(ctsp.getCaseNumber() + "+" + ctsp.getWaybillNumber());
					ctsp.setTallyPreFile("-");
					ctsp.setTallySuffixFile("-");
				}
				submitContainerTallying(ctsp);
				if (te.getFinanceId() != null) {
					finishedTallying(ctsp.getTallyingId(), null);
					reportTallying(ctsp.getTallyingId());
				}
			}
//			FileEntry fe = readZipFile("C:\\Users\\NTBK-021-1006\\Documents\\Tencent Files\\393949022\\FileRecv\\国贸\\国贸\\华南空箱拍照1.zip", "ATLU0015656.jpg");
//			System.out.println(fe.getFileName());
//			System.out.println(fe.getFileUuid());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public void test11(Long fileName) {
		try {
			FileEntry fe = readZipFile("C:\\Users\\NTBK-021-1006\\Documents\\Tencent Files\\393949022\\FileRecv\\111.zip", "CRSU1510113");
			System.out.println(fe.getFileName());
			System.out.println(fe.getFileUuid());
			String[] s = fe.getFileName().split("/");
			String path = "";
			for (int i = 0; i < s.length -1; i++) {
				path += s[i] + "/";
			}
			FileEntry fe1 = readZipFile("C:\\Users\\NTBK-021-1006\\Documents\\Tencent Files\\393949022\\FileRecv\\111.zip", path + "CRSU1510622");
			System.out.println(fe1.getFileName());
			System.out.println(fe1.getFileUuid());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private FileEntry readZipFile(String file, String fileName) throws Exception {
		FileEntry fe = null;
		ZipFile zf = new ZipFile(file);
		InputStream in = new BufferedInputStream(new FileInputStream(file));  
		ZipInputStream zin = new ZipInputStream(in);  
		ZipEntry ze;
		while ((ze = zin.getNextEntry()) != null) {  
			if (ze.isDirectory()) {

			} else {  
				System.out.println("========================"+ze.getName());
				long size = ze.getSize();  
				if (size > 0 && ze.getName().contains(fileName)) {
					BufferedReader br = new BufferedReader(new InputStreamReader(zf.getInputStream(ze)));  
					fe = transferService.uploadFile(ze.getName(),  zf.getInputStream(ze));
					br.close();
					break;
				}  
			}
		}  
		zin.closeEntry();  
		return fe;
	}
}
